//
//  QRCodeViewController.swift
//  DSWeiBo
//
//  Created by Frank Wang on 7/8/16.
//  Copyright © 2016 Frank Wang. All rights reserved.
//
/**
 冲击波约束
 imageView 和View，同高同宽。
 image View水平对齐
 竖直方向，与父View，顶部距离为0；
 目的，是为了制作动画，只需要改变冲击波的竖直方向的约束。
 
 */

import UIKit
import AVFoundation

class QRCodeViewController: UIViewController,UITabBarDelegate,AVCaptureMetadataOutputObjectsDelegate {
        
        //扫描容器高度约束
        @IBOutlet weak var containerHeightCon: NSLayoutConstraint!

        //冲击波视图
        @IBOutlet weak var scanLineView: UIImageView!
        //冲击波视图顶部约束
        @IBOutlet weak var scanLineCons: NSLayoutConstraint!
        
        @IBAction func AlbumBtnClick(sender: UIBarButtonItem) {
        }
        
        //底部视图
        @IBOutlet weak var customTabBar: UITabBar!
        //保存扫描的结果
        @IBOutlet weak var resultLabel: UILabel!
        /**
         监听名片按钮点击
         
         - parameter sender: QRCard
         */
        @IBAction func myCardBtnClick(sender: AnyObject) {
                let vc = QRCodeCardViewController()
                navigationController?.pushViewController(vc, animated: true)
                
        }
        
        @IBAction func closeBtnClick(sender: UIBarButtonItem) {
                dismissViewControllerAnimated(true, completion: nil)
        }

        override func viewDidLoad() {
                super.viewDidLoad()
                //1.设置底部视图默认选中第0ge
                customTabBar.selectedItem = customTabBar.items![0]
                customTabBar.delegate = self
                
                
        }
        
        override func viewWillAppear(animated: Bool) {
                super.viewWillAppear(animated)
                //开始冲击波的动画
                startAnimate()
                
                //开始扫描
                startScan()
        }
        
        private func startScan(){
                //1.判断是否能够将输入添加到会话中
                if !session.canAddInput(deviceInput) {
                        return
                }
                //2.判断是否能够将输出添加到会话中
                if !session.canAddOutput(output) {
                        return
                }
                //3.将输入和输出都添加到会话中
                session.addInput(deviceInput)
                session.addOutput(output)
        
                //4.设置输出能够解析的数据类型
                //设置能够解析的数据类型，一定要在输出对象添加到会话之后设置
                output.metadataObjectTypes = output.availableMetadataObjectTypes
                print(output.availableMetadataObjectTypes)
                //5.设置输出对象的代理，只要解析成功就会通知代理
                output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
                
                //5.0 设置扫描感兴趣的内容,如果想只扫描一张图片，系统自带的是不支持，只能设置让二维码处在某个区域，然后在扫描。
//                output.rectOfInterest = CGRectMake(0.0, 0.0, 0.5, 0.5)
                
                //5.1添加扫描涂层
                view.layer.insertSublayer(previewLayer, atIndex: 0)
                
                //5.2添加绘制涂层到预览涂层上
                previewLayer.addSublayer(drawLayer)
                //6.告诉session开始扫描
                session.startRunning()
        }
        
       private func startAnimate (){
                //让约束从顶部开始
                scanLineCons.constant = -self.containerHeightCon.constant
                view.layoutIfNeeded() //注意，让View来刷新。
                //执行冲击波的动画
                
                UIView.animateWithDuration(2.0, animations: {
                        //修改约束
                        self.scanLineCons.constant = self.containerHeightCon.constant
                        UIView.setAnimationRepeatCount(MAXFLOAT)
                        self.view.layoutIfNeeded()
                        
                        })
        }
        
        //设置二维码的tag为1.
        func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
                //修改容器的高度
                
                self.containerHeightCon.constant = item.tag == 1 ? 300 : 300*0.5
               // 停止动画
                self.scanLineView.layer.removeAllAnimations()
                //重新开始动画
                startAnimate()
        }
        
        //MARK : lazy
        //创建扫描会话
        private lazy var session : AVCaptureSession = {
           
                let av = AVCaptureSession()
                return av
                
        }()
        //拿到输入设备
        
        private lazy var deviceInput : AVCaptureDeviceInput? = {
           let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
                do{
                        let input = try AVCaptureDeviceInput(device: device)
                        return input
                }catch{
                        print(error)
                        return nil
                }
                
                
        }()
        
        //拿到输出对象
        
        private lazy var output : AVCaptureMetadataOutput = AVCaptureMetadataOutput()
        
        //创建预览图层
        private lazy var previewLayer : AVCaptureVideoPreviewLayer = {
                
                //创建预览图层
                let layer = AVCaptureVideoPreviewLayer(session: self.session)
                //设置frame
                layer.frame = UIScreen.mainScreen().bounds
                //设置填充模式，否则4S会奔溃
                layer.videoGravity = AVLayerVideoGravityResizeAspectFill
                return layer
        }()
        //绘制涂层
        private lazy var drawLayer: CALayer = {
                let layer = CALayer()
                layer.frame = UIScreen.mainScreen().bounds
                return layer
        }()
        
        //只要解析到数据就会调用
        func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
                //先清空边框
                clearCorners()
//                要使用stringValue
                //1.获取到扫描到的数据
                resultLabel.text = metadataObjects.last?.stringValue
                resultLabel.sizeToFit()
//                2.获取扫描到的位置
                //转换坐标
                for object in metadataObjects{
                        //2.1.1 判断当前获取到的数据，是否是机器可以识别的
                        if object is AVMetadataMachineReadableCodeObject {
                                let codeObject = previewLayer.transformedMetadataObjectForMetadataObject(object as! AVMetadataObject) as! AVMetadataMachineReadableCodeObject

                                drawCorners(codeObject)
                        }
                }
        }
        /**
         绘制图形
         
         - parameter codeObject: 保存了坐标的对象
         */
        private func drawCorners(codeObject : AVMetadataMachineReadableCodeObject){
                

                
                if codeObject.corners.isEmpty {
                        return
                }
                //1.创建一个图层
                let layer = CAShapeLayer()
                layer.lineWidth = 4
                layer.strokeColor = UIColor.redColor().CGColor
                layer.fillColor = UIColor.clearColor().CGColor
     
                
                //3.绘制路径
                layer.path = cornersPath(codeObject.corners)
                
                //3.将绘制的涂层添加到layer上
                drawLayer.addSublayer(layer)
        }
        
        
        /**
         根据坐标数组生成路径
         
         :param: corners 坐标数组
         
         :returns: 路径
         */
        private func cornersPath(corners: NSArray) -> CGPath
        {
                // 3.1创建路径
                let path = UIBezierPath()
                var point = CGPointZero
                // 3.2移动到第一个点
                var index = 0
                
                //        for i in 0..<codeObject.corners.count {
                //            print(codeObject.corners[i])
                //        }
                
                // 取出第0个点
                CGPointMakeWithDictionaryRepresentation((corners[index] as! CFDictionaryRef), &point)
                path.moveToPoint(point)
                // 3.3设置其它点
                while index < corners.count
                {
                        CGPointMakeWithDictionaryRepresentation((corners[index++] as! CFDictionaryRef), &point)
                        path.addLineToPoint(point)
                }
                // 3.4关闭路径
                path.closePath()
                return path.CGPath
        }
        
        //清空矩形边线
      private  func clearCorners() {
                //1.判断drawLayer上是否有其他图层
                if drawLayer.sublayers == nil || drawLayer.sublayers?.count == 0{
                        return
                }
                
                //2.移除所有图层
                for subLayer in drawLayer.sublayers! {
                        subLayer.removeFromSuperlayer()
                }
        }
}
